package la.iok.hzsvn.lewin.movie.service;

import la.iok.hzsvn.lewin.movie.config.LocalFileSystemProperty;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.dfs.exception.DfsException;
import la.iok.hzsvn.share.dfs.model.DfsDescriptor;
import la.iok.hzsvn.share.dfs.model.DfsResult;
import la.iok.hzsvn.share.dfs.service.AbstractDfsService;
import la.iok.hzsvn.share.utils.PathUtils;
import la.iok.hzsvn.share.utils.StringUtils;

import java.io.*;
import java.util.UUID;

import static la.iok.hzsvn.share.utils.FileUtils.getExtension;

/**
 * 本地文件系统实现的假的分布式文件服务。只能用于测试使用，测试时可以不用部署分布式文件系统
 */
public class LocalFileSystemServiceImpl extends AbstractDfsService {
    private static final int bufferSize = 1024*10;
    private final String ROOT;

    public LocalFileSystemServiceImpl(LocalFileSystemProperty localFileSystemProperty) {
        ROOT = StringUtils.isBlank(localFileSystemProperty.getRootPath())?PathUtils.getPath(): localFileSystemProperty.getRootPath();
    }

    @Override
    public DfsResult uploadFile(String storePath, File file) throws DfsException {
        String targetPath = PathUtils.join(ROOT,storePath);
        File f = new File(targetPath);
        if(!f.exists()){
            try {
                File p = f.getParentFile();
                if(!p.exists()){
                    if(!p.mkdirs()){
                        throw new DfsException("创建文件存储目录失败");
                    }
                }
                if(!f.createNewFile()){
                    throw new DfsException("创建文件失败");
                }
            } catch (IOException e) {
                throw new DfsException("创建文件失败",e);
            }
        }
        try(OutputStream out = new FileOutputStream(targetPath);InputStream is = new FileInputStream(file)){
            byte[] buffer = new byte[bufferSize];
            int len = 0;
            while ((len = is.read(buffer)) > 0){
                out.write(buffer,0,len);
            }
            out.flush();
            return DfsResult.success(dfsFile(storePath));
        }catch (IOException e){
            throw new DfsException("上传文件失败",e);
        }
    }

    @Override
    public DfsResult downloadFile(@NotNull OutputStream outputStream, @NotNull DfsDescriptor descriptor) throws DfsException {
        if(StringUtils.isBlank(descriptor.path())){
           return DfsResult.failure("文件路径不能空");
        }
        String path = PathUtils.join(ROOT,descriptor.path());
        File file = new File(path);
        if(!file.exists()){
            return DfsResult.failure("文件[" + path + "]不存在");
        }
        try(InputStream is = new FileInputStream(file)){
            byte[] buffer = new byte[bufferSize];
            int len = 0;
            while ((len = is.read(buffer)) > 0){
                outputStream.write(buffer,0,len);
            }
            outputStream.flush();
            return DfsResult.success(descriptor);
        }catch (IOException e){
            throw new DfsException("下载文件失败",e);
        }
    }

    @Override
    public DfsResult deleteFile(DfsDescriptor descriptor) throws DfsException {
        if(StringUtils.isBlank(descriptor.path())){
            return DfsResult.success(descriptor);
        }
        String path = PathUtils.join(ROOT,descriptor.path());
        File file = new File(path);
        if(!file.exists()){
            return DfsResult.success(descriptor);
        }
        if(file.delete()){
            return DfsResult.success(descriptor);
        }
        return DfsResult.failure("删除文件[" + path + "]失败");
    }

    @Override
    public DfsDescriptor dfsFile(String path) {
        return new LocalFileDescriptor(path);
    }

    @Override
    public String storePath(String digest, String fileName) {
        String id;
        String path;
        do {
            id = UUID.randomUUID().toString().replaceAll("-","");
            path = defaultStorePath(id,fileName);
        }while (existRelativePath(path));
        return path;
    }

    @Override
    public long getFileLength(DfsDescriptor descriptor) {
        if(exist(descriptor)){
            String path = PathUtils.join(ROOT,descriptor.path());
            File file = new File(path);
            return file.length();
        }
        return 0;
    }

    @Override
    public boolean exist(DfsDescriptor descriptor) {
        return existRelativePath(descriptor.path());
    }

    private boolean existRelativePath(String relativePath){
        if(StringUtils.isBlank(relativePath)){
            return false;
        }
        String path = PathUtils.join(ROOT,relativePath);
        File file = new File(path);
        return file.exists();
    }

    private static class LocalFileDescriptor implements DfsDescriptor{
        private final String filePath;

        public LocalFileDescriptor(String filePath) {
            this.filePath = filePath;
        }

        @Override
        public String path() {
            return filePath;
        }
    }
}
